﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using IPC.Communication.Core;
using IPC.Communication.Core.Address;
using IPC.Communication.Core.IMessage;
using IPC.Communication.Core.Net;
using IPC.Communication.Profinet.Melsec.Helper;
using IPC.Communication.Reflection;

namespace IPC.Communication.Profinet.Melsec
{
    public class MelsecMcAsciiNet : NetworkDeviceBase, IReadWriteMc, IReadWriteDevice, IReadWriteNet
    {
        private McType _mcType = McType.MCAscii;
        private byte _networkNumber = 0;
        private byte _networkStationNumber = 0;

        public McType McType
        {
            get { return _mcType; }
            set { _mcType = value; }
        }

        public byte NetworkNumber
        {
            get { return _networkNumber; }
            set { _networkNumber = value; }
        }


        public byte NetworkStationNumber
        {
            get { return _networkStationNumber; }
            set { _networkStationNumber = value; }
        }


        public MelsecMcAsciiNet()
        {
            base.WordLength = 1;
            LogMsgFormatBinary = false;
            base.ByteTransform = new RegularByteTransform();
        }

        public MelsecMcAsciiNet(string ipAddress, int port)
            : this()
        {
            IpAddress = ipAddress;
            Port = port;
        }

        protected override INetMessage GetNewNetMessage()
        {
            return new MelsecQnA3EAsciiMessage();
        }

        public virtual OperateResult<McAddressData> McAnalysisAddress(string address, ushort length)
        {
            return McAddressData.ParseMelsecFrom(address, length);
        }

        protected override byte[] PackCommandWithHeader(byte[] command)
        {
            return McAsciiHelper.PackMcCommand(command, NetworkNumber, NetworkStationNumber);
        }

        protected override OperateResult<byte[]> UnpackResponseContent(byte[] send, byte[] response)
        {
            OperateResult operateResult = McAsciiHelper.CheckResponseContent(response);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            return OperateResult.CreateSuccessResult(response.RemoveBegin(22));
        }

        public byte[] ExtractActualData(byte[] response, bool isBit)
        {
            return McAsciiHelper.ExtractActualDataHelper(response, isBit);
        }

        [HslMqttApi("ReadByteArray", "")]
        public override OperateResult<byte[]> Read(string address, ushort length)
        {
            return McHelper.Read(this, address, length);
        }

        [HslMqttApi("WriteByteArray", "")]
        public override OperateResult Write(string address, byte[] value)
        {
            return McHelper.Write(this, address, value);
        }

        //[AsyncStateMachine(typeof(<ReadAsync>d__19))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult<byte[]>> ReadAsync(string address, ushort length)
        //{
        //    <ReadAsync>d__19 stateMachine = new <ReadAsync>d__19();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__20))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult> WriteAsync(string address, byte[] value)
        //{
        //    <WriteAsync>d__20 stateMachine = new <WriteAsync>d__20();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi("随机读取PLC的数据信息，可以跨地址，跨类型组合，但是每个地址只能读取一个word，也就是2个字节的内容。收到结果后，需要自行解析数据")]
        public OperateResult<byte[]> ReadRandom(string[] address)
        {
            return McHelper.ReadRandom(this, address);
        }

        [HslMqttApi(ApiTopic = "ReadRandoms", Description = "随机读取PLC的数据信息，可以跨地址，跨类型组合，每个地址是任意的长度。收到结果后，需要自行解析数据，目前只支持字地址，比如D区，W区，R区，不支持X，Y，M，B，L等等")]
        public OperateResult<byte[]> ReadRandom(string[] address, ushort[] length)
        {
            return McHelper.ReadRandom(this, address, length);
        }

        public OperateResult<short[]> ReadRandomInt16(string[] address)
        {
            return McHelper.ReadRandomInt16(this, address);
        }

        public OperateResult<ushort[]> ReadRandomUInt16(string[] address)
        {
            return McHelper.ReadRandomUInt16(this, address);
        }

        //[AsyncStateMachine(typeof(<ReadRandomAsync>d__25))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte[]>> ReadRandomAsync(string[] address)
        //{
        //    <ReadRandomAsync>d__25 stateMachine = new <ReadRandomAsync>d__25();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadRandomAsync>d__26))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte[]>> ReadRandomAsync(string[] address, ushort[] length)
        //{
        //    <ReadRandomAsync>d__26 stateMachine = new <ReadRandomAsync>d__26();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadRandomInt16Async>d__27))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<short[]>> ReadRandomInt16Async(string[] address)
        //{
        //    <ReadRandomInt16Async>d__27 stateMachine = new <ReadRandomInt16Async>d__27();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<short[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadRandomUInt16Async>d__28))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<ushort[]>> ReadRandomUInt16Async(string[] address)
        //{
        //    <ReadRandomUInt16Async>d__28 stateMachine = new <ReadRandomUInt16Async>d__28();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<ushort[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi("ReadBoolArray", "")]
        public override OperateResult<bool[]> ReadBool(string address, ushort length)
        {
            return McHelper.ReadBool(this, address, length);
        }

        [HslMqttApi("WriteBoolArray", "")]
        public override OperateResult Write(string address, bool[] values)
        {
            return McHelper.Write(this, address, values);
        }

        //[AsyncStateMachine(typeof(<ReadBoolAsync>d__31))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult<bool[]>> ReadBoolAsync(string address, ushort length)
        //{
        //    <ReadBoolAsync>d__31 stateMachine = new <ReadBoolAsync>d__31();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__32))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult> WriteAsync(string address, bool[] values)
        //{
        //    <WriteAsync>d__32 stateMachine = new <WriteAsync>d__32();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.values = values;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi(ApiTopic = "ReadExtend", Description = "读取扩展的数据信息，需要在原有的地址，长度信息之外，输入扩展值信息")]
        public OperateResult<byte[]> ReadExtend(ushort extend, string address, ushort length)
        {
            return McHelper.ReadExtend(this, extend, address, length);
        }

        //[AsyncStateMachine(typeof(<ReadExtendAsync>d__34))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte[]>> ReadExtendAsync(ushort extend, string address, ushort length)
        //{
        //    <ReadExtendAsync>d__34 stateMachine = new <ReadExtendAsync>d__34();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.extend = extend;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi(ApiTopic = "ReadMemory", Description = "读取缓冲寄存器的数据信息，地址直接为偏移地址")]
        public OperateResult<byte[]> ReadMemory(string address, ushort length)
        {
            return McHelper.ReadMemory(this, address, length);
        }

        //[AsyncStateMachine(typeof(<ReadMemoryAsync>d__36))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte[]>> ReadMemoryAsync(string address, ushort length)
        //{
        //    <ReadMemoryAsync>d__36 stateMachine = new <ReadMemoryAsync>d__36();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi(ApiTopic = "ReadSmartModule", Description = "读取智能模块的数据信息，需要指定模块地址，偏移地址，读取的字节长度")]
        public OperateResult<byte[]> ReadSmartModule(ushort module, string address, ushort length)
        {
            return McHelper.ReadSmartModule(this, module, address, length);
        }

        //[AsyncStateMachine(typeof(<ReadSmartModuleAsync>d__38))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte[]>> ReadSmartModuleAsync(ushort module, string address, ushort length)
        //{
        //    <ReadSmartModuleAsync>d__38 stateMachine = new <ReadSmartModuleAsync>d__38();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.module = module;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi(ApiTopic = "RemoteRun", Description = "远程Run操作")]
        public OperateResult RemoteRun()
        {
            return McHelper.RemoteRun(this);
        }

        [HslMqttApi(ApiTopic = "RemoteStop", Description = "远程Stop操作")]
        public OperateResult RemoteStop()
        {
            return McHelper.RemoteStop(this);
        }

        [HslMqttApi(ApiTopic = "RemoteReset", Description = "LED 熄灭 出错代码初始化")]
        public OperateResult RemoteReset()
        {
            return McHelper.RemoteReset(this);
        }

        [HslMqttApi(ApiTopic = "ReadPlcType", Description = "读取PLC的型号信息，例如 Q02HCPU")]
        public OperateResult<string> ReadPlcType()
        {
            return McHelper.ReadPlcType(this);
        }

        [HslMqttApi(ApiTopic = "ErrorStateReset", Description = "LED 熄灭 出错代码初始化")]
        public OperateResult ErrorStateReset()
        {
            return McHelper.ErrorStateReset(this);
        }

        //[AsyncStateMachine(typeof(<RemoteRunAsync>d__44))]
        //[DebuggerStepThrough]
        //public Task<OperateResult> RemoteRunAsync()
        //{
        //    <RemoteRunAsync>d__44 stateMachine = new <RemoteRunAsync>d__44();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<RemoteStopAsync>d__45))]
        //[DebuggerStepThrough]
        //public Task<OperateResult> RemoteStopAsync()
        //{
        //    <RemoteStopAsync>d__45 stateMachine = new <RemoteStopAsync>d__45();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<RemoteResetAsync>d__46))]
        //[DebuggerStepThrough]
        //public Task<OperateResult> RemoteResetAsync()
        //{
        //    <RemoteResetAsync>d__46 stateMachine = new <RemoteResetAsync>d__46();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadPlcTypeAsync>d__47))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<string>> ReadPlcTypeAsync()
        //{
        //    <ReadPlcTypeAsync>d__47 stateMachine = new <ReadPlcTypeAsync>d__47();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<string>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ErrorStateResetAsync>d__48))]
        //[DebuggerStepThrough]
        //public Task<OperateResult> ErrorStateResetAsync()
        //{
        //    <ErrorStateResetAsync>d__48 stateMachine = new <ErrorStateResetAsync>d__48();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public override string ToString()
        {
            return String.Format("MelsecMcAsciiNet[{0}:{1}]", IpAddress, Port);
        }
    }
}
